home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / dev / sun4c.md / devSCSIC90.c < prev    next >
C/C++ Source or Header  |  1991-08-01  |  49KB  |  1,790 lines

  1. /* 
  2.  * devSCSIC90.c --
  3.  *
  4.  *    Routines specific to the SCSI NCR 53C9X Host Adaptor.  This adaptor is
  5.  *    based on the NCR 53C90 chip.
  6.  *    The 53C90 supports connect/dis-connect.
  7.  *
  8.  * Copyright 1988 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /sprite/src/kernel/dev/ds5000.md/RCS/devSCSIC90.c,v 1.5 91/08/01 20:57:44 mottsmth Exp $ SPRITE (Berkeley)";
  20. #endif /* not lint */
  21.  
  22. #include "sprite.h"
  23. #include "scsiC90.h"
  24. #include "mach.h"
  25. #include "dev.h"
  26. #include "scsiHBA.h"
  27. #include "scsiDevice.h"
  28. #include "sync.h"
  29. #include "stdio.h"
  30. #include "stdlib.h"
  31. #include "string.h"
  32. #include "bstring.h"
  33. #include "devSCSIC90.h"
  34. #include "devSCSIC90Int.h"
  35.  
  36. /*
  37.  * Forward declarations.  
  38.  */
  39.  
  40. static void        PrintMsg _ARGS_ ((unsigned int msg));
  41. static void        PrintPhase _ARGS_ ((unsigned int phase));
  42. static void        PrintLastPhase _ARGS_ ((unsigned int phase));
  43. static ReturnStatus     SendCommand _ARGS_ ((Device *devPtr,
  44.                                              ScsiCmd *scsiCmdPtr));
  45. static void             PrintRegs _ARGS_((volatile CtrlRegs *regsPtr));
  46. static void             PerformCmdDone _ARGS_((Controller *ctrlPtr,
  47.                            ReturnStatus status));
  48. static ReturnStatus     PerformSelect _ARGS_((Controller *ctrlPtr,
  49.                           unsigned int interruptReg,
  50.                           unsigned int sequenceReg));
  51. static ReturnStatus     PerformDataXfer _ARGS_((Controller *ctrlPtr,
  52.                           unsigned int interruptReg,
  53.                           unsigned int statusReg));
  54. static ReturnStatus     PerformStatus _ARGS_((Controller *ctrlPtr,
  55.                           unsigned int interruptReg));
  56. static ReturnStatus     PerformMsgIn _ARGS_(( Controller *ctrlPtr));
  57. static ReturnStatus     PerformReselect _ARGS_(( Controller *ctrlPtr,
  58.                           unsigned int interruptReg));
  59. static ReturnStatus     PerformExtendedMsgIn _ARGS_(( Controller *ctrlPtr,
  60.                           unsigned int message));
  61. static int              SpecialSenseProc _ARGS_((void));
  62. static void             PutCircBuf _ARGS_((int type, char *object));
  63.  
  64. /*
  65.  * devSCSIC90Debug - debugging level
  66.  *    2 - normal level
  67.  *    4 - one print per command in the normal case
  68.  *    5 - traces interrupts
  69.  */
  70. int devSCSIC90Debug = 2;
  71. Controller *Controllers[MAX_SCSIC90_CTRLS];
  72.  
  73. char        circBuf[CIRCBUFLEN] = {""};
  74. int         circHead = 0;
  75. char numTab[16] = {
  76.     '0', '1', '2', '3', '4', '5', '6', '7',
  77.     '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
  78.     };
  79.      
  80.  
  81.  
  82. /*
  83.  *----------------------------------------------------------------------
  84.  *
  85.  * SendCommand --
  86.  *
  87.  *      Send a command to a SCSI controller.
  88.  *    NOTE: The caller is assumed to have the master lock of the controller
  89.  *    to which the device is attached held.
  90.  *      
  91.  *
  92.  * Results:
  93.  *    An error code.
  94.  *
  95.  * Side effects:
  96.  *    Those of the command (Read, write etc.)
  97.  *
  98.  *----------------------------------------------------------------------
  99.  */
  100. static ReturnStatus
  101. SendCommand(devPtr, scsiCmdPtr)
  102.     Device     *devPtr;        /* Device to sent to. */
  103.     ScsiCmd    *scsiCmdPtr;        /* Command to send. */
  104. {
  105.     volatile CtrlRegs    *regsPtr; /* Host Adaptor registers */
  106.     char    *charPtr;
  107.     Controller    *ctrlPtr;
  108.     int i;
  109.     int size;                /* Number of bytes to transfer */
  110.  
  111.     /*
  112.      * Set current active device and command for this controller.
  113.      */
  114.     ctrlPtr = devPtr->ctrlPtr;
  115.     regsPtr = ctrlPtr->regsPtr;
  116.  
  117.     if (ctrlPtr->devPtr != (Device *)NIL) {
  118.     panic("SCSIC90Command: can't send: host is busy\n");
  119.     }
  120.  
  121.     SET_CTRL_BUSY(ctrlPtr,devPtr);
  122.     SET_DEV_BUSY(devPtr, scsiCmdPtr);
  123.  
  124.     devPtr->scsiCmdPtr   = scsiCmdPtr;
  125.     size = scsiCmdPtr->bufferLen;
  126.     if (size == 0) {
  127.     devPtr->dmaState = DMA_INACTIVE;
  128.     } else {
  129.     devPtr->dmaState = (scsiCmdPtr->dataToDevice) ? DMA_SEND :
  130.                             DMA_RECEIVE;
  131.     }
  132.  
  133.     PUTCIRCBUF(CSTR, "send: targ ");
  134.     PUTCIRCBUF(CBYTE, (char *)devPtr->targetID);
  135.     PUTCIRCBUF(CSTR, ";cmd ");
  136.     PUTCIRCBUF(CINT, (char *)scsiCmdPtr);
  137.     PUTCIRCBUF(CSTR,";buf ");
  138.     PUTCIRCBUF(CINT, (char *)scsiCmdPtr->buffer);
  139.     PUTCIRCBUF(CSTR, ";len ");
  140.     PUTCIRCBUF(CINT, (char *)size);
  141.     PUTCIRCBUF(CSTR,";op ");
  142.     PUTCIRCBUF(CBYTE, (char *)scsiCmdPtr->commandBlock[0]);
  143.     PUTCIRCNULL;
  144.  
  145.     /*
  146.      * SCSI SELECTION.
  147.      */
  148.  
  149.     /*
  150.      * Set phase to selection and command phase so that we know what's happened
  151.      * in the next phase.
  152.      */
  153.     devPtr->lastPhase = PHASE_SELECTION;    /* Selection & command phase.*/
  154.     devPtr->commandStatus = 0;            /* No status yet. */
  155.     devPtr->activeBufPtr = scsiCmdPtr->buffer;
  156.     devPtr->activeBufLen = scsiCmdPtr->bufferLen;
  157.     /* Load select/reselect bus ID register with target ID. */
  158.     regsPtr->scsi_ctrl.write.destID = devPtr->targetID;
  159.     /* Load select/reselect timeout period. */
  160.     regsPtr->scsi_ctrl.write.timeout = SELECT_TIMEOUT;
  161.     /* Zero value for asynchronous transfer. */
  162.     regsPtr->scsi_ctrl.write.synchOffset = devPtr->synchOffset;
  163.     if (devPtr->synchOffset != 0) {
  164.     regsPtr->scsi_ctrl.write.synchPer = devPtr->synchPeriod;
  165.     }
  166.     /* Set the clock conversion register. */
  167.     regsPtr->scsi_ctrl.write.clockConv = CLOCKCONV;
  168.  
  169.     EMPTY_BUFFER();
  170.  
  171.     /* 
  172.      * There are 3 selection possibilities:
  173.      * 1) Without Attention (NATN) which says we don't do disconnect/reselect.
  174.      *    No need to use this anymore.
  175.      * 2) With Attention (ATN) which goes through arbitration, selection
  176.      *    and command phases, announcing that we do disconnect/reselect.
  177.      *    The usual mode.
  178.      * 3) With attention and stop (ATNS) which just goes through 
  179.      *    arbitration and selection phases and stops.  This gives
  180.      *    us a chance to send another message after the IDENTIFY msg
  181.      *    before sending the command.  For use in sending the 1st
  182.      *    message of the synchronous data xfer negotiation.
  183.      */
  184.  
  185.     if (scsiCmdPtr->commandBlockLen != 6 &&
  186.     scsiCmdPtr->commandBlockLen != 10 &&
  187.     scsiCmdPtr->commandBlockLen != 12) {
  188.     printf("%s: Command is wrong length.\n");
  189.     PUTCIRCBUF(CSTR,"send: bad cmd len\n");
  190.     PUTCIRCNULL;
  191.     return DEV_INVALID_ARG;     /* Is this the correct error? */
  192.     }
  193.  
  194.  
  195.     regsPtr->scsi_ctrl.write.FIFO = SCSI_DIS_REC_IDENTIFY | devPtr->handle.LUN;
  196.  
  197.     if ((devPtr->synchPeriod < MIN_SYNCH_PERIOD) &&
  198.     (devPtr->msgFlag & ENABLEEXTENDEDMSG)) {
  199.     devPtr->msgFlag |= REQEXTENDEDMSG;
  200.     EMPTY_BUFFER();
  201.     regsPtr->scsi_ctrl.write.command = CR_SLCT_ATNS;
  202.     PUTCIRCBUF(CSTR,"send ATNS; per ");
  203.     } else {
  204.     /* Load FIFO with 6, 10, or 12 byte scsi command. */
  205.     charPtr = scsiCmdPtr->commandBlock;
  206.     for (i = 0; i < scsiCmdPtr->commandBlockLen; i++) {
  207.         regsPtr->scsi_ctrl.write.FIFO = *charPtr;
  208.         charPtr++;
  209.     }
  210.     PUTCIRCBUF(CSTR,"send ATN; per ");
  211.     EMPTY_BUFFER();
  212.     regsPtr->scsi_ctrl.write.command = CR_SLCT_ATN;
  213.     }
  214.     PUTCIRCBUF(CBYTE,(char *)(devPtr->synchPeriod));
  215.     PUTCIRCBUF(CSTR,"; off ");
  216.     PUTCIRCBUF(CBYTE,(char *)(devPtr->synchOffset));
  217.     PUTCIRCBUF(CSTR,"; cmd ");
  218.     PUTCIRCBUF(CBYTE,(char *)(*scsiCmdPtr->commandBlock));
  219.     PUTCIRCNULL;
  220.  
  221.     return SUCCESS;
  222. }
  223.  
  224.  
  225. /*
  226.  *----------------------------------------------------------------------
  227.  *
  228.  * RequestDone --
  229.  *
  230.  *    Process a request that has finished. Unless a SCSI check condition
  231.  *    bit is present in the status returned, the request call back
  232.  *    function is called.  If check condition is set we fire off a
  233.  *    SCSI REQUEST SENSE to get the error sense bytes from the device.
  234.  *
  235.  * Results:
  236.  *    None.
  237.  *
  238.  * Side effects:
  239.  *    The call back function may be called.
  240.  *
  241.  *----------------------------------------------------------------------
  242.  */
  243.  
  244. static void
  245. RequestDone(devPtr,scsiCmdPtr,status,scsiStatusByte,amountTransferred)
  246.     Device    *devPtr;    /* Device for request. */
  247.     ScsiCmd    *scsiCmdPtr;    /* Request that finished. */
  248.     ReturnStatus status;    /* Status returned. */
  249.     unsigned char scsiStatusByte;    /* SCSI Status Byte. */
  250.     int        amountTransferred; /* Amount transferred by command. */
  251. {
  252.     ReturnStatus    senseStatus;
  253.     Controller            *ctrlPtr = devPtr->ctrlPtr;
  254.     int i;
  255.  
  256.     PUTCIRCBUF(CSTR,"done: targ ");
  257.     PUTCIRCBUF(CBYTE, (char *)devPtr->targetID);
  258.     PUTCIRCBUF(CSTR,";rc ");
  259.     PUTCIRCBUF(CBYTE, (char *)status);
  260.     PUTCIRCBUF(CSTR,";stat ");
  261.     PUTCIRCBUF(CBYTE, (char *)scsiStatusByte);
  262.     PUTCIRCBUF(CSTR,";cnt ");
  263.     PUTCIRCBUF(CBYTE, (char *)amountTransferred);
  264.     PUTCIRCNULL;
  265.  
  266.     SET_CTRL_FREE(ctrlPtr);
  267.  
  268.     /*
  269.      * First check to see if this is the reponse of a HBA-driver generated 
  270.      * REQUEST SENSE command.  If this is the case, we can process
  271.      * the callback of the frozen command for this device and
  272.      * allow the flow of command to the device to be resummed.
  273.      */
  274.     if (scsiCmdPtr->doneProc == SpecialSenseProc) {
  275.     PUTCIRCBUF(CSTR,"sense data:");
  276.     for (i=0; i<amountTransferred; i++) {
  277.         circBuf[circHead] = ' ';
  278.         circHead = (circHead + 1) % CIRCBUFLEN;
  279.         PUTCIRCBUF(CBYTE, (char *)(devPtr->senseBuffer[i]));
  280.     }
  281.     PUTCIRCNULL;
  282.         MASTER_UNLOCK(&(ctrlPtr->mutex));
  283.     (devPtr->frozen.scsiCmdPtr->doneProc)(devPtr->frozen.scsiCmdPtr, 
  284.         SUCCESS,
  285.         devPtr->frozen.statusByte, 
  286.         devPtr->frozen.amountTransferred,
  287.         amountTransferred,
  288.         devPtr->senseBuffer);
  289.          MASTER_LOCK(&(ctrlPtr->mutex));
  290.      SET_DEV_FREE(devPtr);
  291.      return;
  292.     }
  293.     /*
  294.      * This must be an outside request finishing. If the request 
  295.      * suffered an error or the HBA or the scsi status byte
  296.      * says there is no error sense present, we can do the
  297.      * callback and free the controller.
  298.      */
  299.     if ((status != SUCCESS) ||
  300.     (scsiStatusByte != SCSI_STATUS_CHECK)) { 
  301.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  302.     PUTCIRCBUF(CSTR,"done: callback before...");
  303.     (scsiCmdPtr->doneProc)(scsiCmdPtr, status, scsiStatusByte,
  304.                    amountTransferred, 0, (char *) 0);
  305.     MASTER_LOCK(&(ctrlPtr->mutex));
  306.     PUTCIRCBUF(CSTR,"after");
  307.     PUTCIRCNULL;
  308.     SET_DEV_FREE(devPtr);
  309.     return;
  310.     } 
  311.     /*
  312.      * If we got here than the SCSI command came back from the device
  313.      * with the CHECK bit set in the status byte.
  314.      * Need to perform a REQUEST SENSE.  Move the current request 
  315.      * into the frozen state and issue a REQUEST SENSE. 
  316.      */
  317.  
  318.     PUTCIRCBUF(CSTR,"done: issue sense");
  319.     PUTCIRCNULL;
  320.     devPtr->synchPeriod = 0;
  321.     devPtr->synchOffset = 0;
  322.     devPtr->frozen.scsiCmdPtr = scsiCmdPtr;
  323.     devPtr->frozen.statusByte = scsiStatusByte;
  324.     devPtr->frozen.amountTransferred = amountTransferred;
  325.     DevScsiSenseCmd((ScsiDevice *)devPtr, DEV_MAX_SENSE_BYTES, 
  326.             devPtr->senseBuffer, &(devPtr->SenseCmd));
  327.     devPtr->SenseCmd.doneProc = SpecialSenseProc;
  328.     senseStatus = SendCommand(devPtr, &(devPtr->SenseCmd));
  329.     
  330.    /*
  331.      * If we got an HBA error on the REQUEST SENSE we end the outside 
  332.      * command with the SUCCESS status but zero sense bytes returned.
  333.      */
  334.     if (senseStatus != SUCCESS) {
  335.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  336.     (scsiCmdPtr->doneProc)(scsiCmdPtr, status, scsiStatusByte,
  337.                    amountTransferred, 0, (char *) 0);
  338.         MASTER_LOCK(&(ctrlPtr->mutex));
  339.     SET_DEV_FREE(devPtr);
  340.     }
  341.  
  342. }
  343.  
  344. /*
  345.  *----------------------------------------------------------------------
  346.  *
  347.  * DevEntryAvailProc --
  348.  *
  349.  *    Act upon an entry becomming available in the queue for this
  350.  *    controller. This routine is the Dev_Queue callback function that
  351.  *    is called whenever work becomes available for this controller. 
  352.  *    If the controller is not already busy we dequeue and start the
  353.  *    request.
  354.  *    NOTE: This routine is also called from DevSCSIC90Intr to start the
  355.  *    next request after the previously one finishes.
  356.  *
  357.  * Results:
  358.  *    None.
  359.  *
  360.  * Side effects:
  361.  *    Request may be dequeue and submitted to the device. Request callback
  362.  *    function may be called.
  363.  *
  364.  *----------------------------------------------------------------------
  365.  */
  366.  
  367. Boolean
  368. DevEntryAvailProc(clientData, newRequestPtr) 
  369.    ClientData    clientData;    /* Really the Device this request ready. */
  370.    List_Links *newRequestPtr;    /* The new SCSI request. */
  371. {
  372.     Device        *devPtr; 
  373.     Controller         *ctrlPtr;
  374.     ScsiCmd        *scsiCmdPtr = (ScsiCmd *)newRequestPtr;
  375.     ReturnStatus    status;
  376.  
  377.     devPtr = (Device *) clientData;
  378.     ctrlPtr = devPtr->ctrlPtr;
  379.     /*
  380.      * If we are busy (have an active request) just return. Otherwise 
  381.      * start the request.
  382.      */
  383.     
  384.     if ((IS_CTRL_FREE(ctrlPtr)) &&  (IS_DEV_FREE(devPtr))) {
  385.     PUTCIRCBUF(CSTR,"EAP: exec targ ");
  386.     PUTCIRCBUF(CBYTE, (char *)(devPtr->targetID));
  387.     PUTCIRCBUF(CSTR,"; mask ");
  388.     PUTCIRCBUF(CBYTE, (char *)(ctrlPtr->devQueuesMask));
  389.     PUTCIRCBUF(CSTR,"; cmd ptr ");
  390.     PUTCIRCBUF(CINT, (char *)newRequestPtr);
  391.     PUTCIRCNULL;
  392.     } else {
  393.     PUTCIRCBUF(CSTR,"EAP: NQ targ ");
  394.     PUTCIRCBUF(CBYTE, (char *)(devPtr->targetID));
  395.     PUTCIRCBUF(CSTR,"; mask ");
  396.     PUTCIRCBUF(CBYTE, (char *)(ctrlPtr->devQueuesMask));
  397.     PUTCIRCBUF(CSTR,"; cmd ptr ");
  398.     PUTCIRCBUF(CINT,(char *)newRequestPtr);
  399.     PUTCIRCBUF(CSTR,"; intDev ");
  400.     PUTCIRCBUF(CINT,(char *)(ctrlPtr->interruptDevPtr));
  401.     if (ctrlPtr->interruptDevPtr != (Device *)NIL) {
  402.         PUTCIRCBUF(CSTR,"; intDevCmd ");
  403.         PUTCIRCBUF(CINT,(char *)(ctrlPtr->interruptDevPtr->scsiCmdPtr));
  404.     }
  405.     PUTCIRCNULL;
  406.     return FALSE;
  407.     }
  408.  
  409. again:
  410.     scsiCmdPtr = (ScsiCmd *) newRequestPtr;
  411.     devPtr = (Device *) clientData;
  412.     status = SendCommand(devPtr, scsiCmdPtr);
  413.  
  414.     /*    
  415.      * If the command couldn't be started do the callback function.
  416.      */
  417.     if (status != SUCCESS) {
  418.      PUTCIRCBUF(CSTR,"eap: send fail");
  419.      PUTCIRCNULL;
  420.      RequestDone(devPtr,scsiCmdPtr,status,0,0);
  421.      newRequestPtr = Dev_QueueGetNextFromSet(ctrlPtr->devQueues,
  422.                          ctrlPtr->devQueuesMask,
  423.                          &clientData);
  424.     if (newRequestPtr != (List_Links *) NIL) { 
  425.         PUTCIRCBUF(CSTR,"eap: no cmd");
  426.         PUTCIRCNULL;
  427.         goto again;
  428.     } else {
  429.         PUTCIRCBUF(CSTR,"eap: cmd");
  430.         PUTCIRCBUF(CINT,(char *)newRequestPtr);
  431.         PUTCIRCNULL;
  432.     }
  433.     }
  434.  
  435.     return TRUE;
  436.  
  437. }   
  438.  
  439.  
  440. /*
  441.  *----------------------------------------------------------------------
  442.  *
  443.  * DevSCSIC90Intr --
  444.  *
  445.  * Handle interrupts from the SCSI controller.
  446.  *
  447.  * Results:
  448.  *    TRUE if an SCSIC90 controller was responsible for the interrupt
  449.  *    and this routine handled it.
  450.  *
  451.  * Side effects:
  452.  *    Usually a process is notified that an I/O has completed.
  453.  *      Extreme headaches from trying to follow this absurd code.
  454.  * 
  455.  * Note:
  456.  *      Cannot use printf for debugging in this routine since 
  457.  *      printf re-enables interrupts.
  458.  *
  459.  *----------------------------------------------------------------------
  460.  */
  461. Boolean 
  462. DevSCSIC90Intr(clientDataArg)
  463.     ClientData    clientDataArg;
  464. {
  465.     Controller        *ctrlPtr;
  466.     volatile CtrlRegs    *regsPtr;
  467.     Device        *devPtr;
  468.     unsigned char    phase;
  469.     ReturnStatus    status = SUCCESS;
  470.     unsigned char    interruptReg;
  471.     unsigned char    statusReg;
  472.     unsigned char    sequenceReg;
  473.     int                 i;
  474.     char            *charPtr;
  475.     char            tempChar;
  476.  
  477.     ctrlPtr = (Controller *) clientDataArg;
  478.     regsPtr = ctrlPtr->regsPtr;
  479.     devPtr = ctrlPtr->devPtr;
  480.  
  481.     MASTER_LOCK(&(ctrlPtr->mutex));
  482.  
  483.     /* Read registers.
  484.      * reading the interrupt register clears the status and sequence
  485.      * registers so it must be read last.
  486.      */
  487.     statusReg = regsPtr->scsi_ctrl.read.status;
  488.     sequenceReg = regsPtr->scsi_ctrl.read.sequence;
  489.     interruptReg = regsPtr->scsi_ctrl.read.interrupt;
  490.     phase = statusReg & SR_PHASE;
  491.     sequenceReg &= SEQ_MASK;
  492.  
  493.     PUTCIRCBUF(CSTR,"intr: dev ");
  494.     PUTCIRCBUF(CINT,(char *)devPtr);
  495.     PUTCIRCBUF(CSTR,";int ");
  496.     PUTCIRCBUF(CBYTE, (char *)interruptReg);
  497.     PUTCIRCBUF(CSTR,";stat ");
  498.     PUTCIRCBUF(CBYTE, (char *)statusReg);
  499.     PUTCIRCBUF(CSTR,";seq ");
  500.     PUTCIRCBUF(CBYTE, (char *)sequenceReg);
  501.     if (devPtr != (Device *)NIL) {
  502.     PUTCIRCBUF(CSTR,";last ");
  503.     PUTCIRCBUF(CBYTE, (char *)devPtr->lastPhase);
  504.     }
  505.     PUTCIRCNULL;
  506.  
  507. /*    printf("interruptReg 0x%02x, statusReg 0x%02x, sequenceReg 0x%02x\n",
  508.         interruptReg, statusReg, sequenceReg);
  509. */
  510.     /* Check for errors. */
  511.     if (statusReg & SR_GE) {
  512.     panic("gross error 1\n");
  513.     printf("%s: some gross error happened.\n",
  514.         devPtr->handle.locationName);
  515.     status = FAILURE;
  516.     }
  517.     if (statusReg & SR_PE) {
  518.     printf("%s: a parity error happened.\n",
  519.         devPtr->handle.locationName);
  520.     status = FAILURE;
  521.     }
  522.  
  523.     if (interruptReg & IR_SCSI_RST) {
  524.     printf("%s: SCSI reset detected.\n",
  525.         devPtr->handle.locationName);
  526.     status = FAILURE;
  527.     }
  528.     if (interruptReg & IR_ILL_CMD) {
  529.     if (ctrlPtr->interruptDevPtr != (Device *)NIL) {
  530.         PUTCIRCBUF(CSTR,"ignoring illegal cmd interrupt");
  531.         PUTCIRCNULL;
  532.         MASTER_UNLOCK(&(ctrlPtr->mutex));
  533.         return TRUE;
  534.     } else {
  535.         printf("%s: illegal command.\n",
  536.            devPtr->handle.locationName);
  537.         status = FAILURE;
  538.     }
  539.     }
  540.     if (interruptReg & IR_SLCT_ATN) {
  541.     printf("%s: scsi controller selected with ATN which we don't allow.\n",
  542.         devPtr->handle.locationName);
  543.     status = FAILURE;
  544.     }
  545.     if (interruptReg & IR_SLCT) {
  546.     printf("%s: scsi controller selected as target which we don't allow.\n",
  547.         devPtr->handle.locationName);
  548.     status = FAILURE;
  549.     }
  550.     if (interruptReg & IR_RESLCT) {
  551.     PerformReselect(ctrlPtr, interruptReg);
  552.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  553.     return TRUE;
  554.     }
  555.     if (IS_CTRL_FREE(ctrlPtr)) {
  556.     if (status == SUCCESS)
  557.         panic("SCSIC90: Got interrupt but ctrl is free.\n");
  558.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  559.     return TRUE;
  560.     }
  561.  
  562.  
  563.     /* Where did we come from? */
  564.     switch (devPtr->lastPhase) {
  565.     case PHASE_COMMAND:
  566.     break;
  567.     case PHASE_BUS_FREE:
  568.     /* nothing happening yet. */
  569.     break;
  570.     case PHASE_SELECTION:
  571.     status = PerformSelect(ctrlPtr, interruptReg, sequenceReg);
  572.     break;
  573.     case PHASE_DATA_IN:
  574. #ifdef sun4c
  575.     /* Drain remaining bytes in pack register to memory. */
  576.     dmaRegsPtr->ctrl |= DMA_DRAIN;
  577. #endif
  578.     status = PerformDataXfer(ctrlPtr, interruptReg, statusReg);
  579.     break;
  580.     case PHASE_DATA_OUT:
  581.     status = PerformDataXfer(ctrlPtr, interruptReg, statusReg);
  582.     break;
  583.     case PHASE_STATUS:
  584.     status = PerformStatus(ctrlPtr, interruptReg);
  585.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  586.     return TRUE;
  587.     break;
  588.     case PHASE_MSG_OUT:
  589.     break;
  590.     case PHASE_MSG_IN:
  591.     status = PerformMsgIn(ctrlPtr);
  592.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  593.     return TRUE;
  594.     break;
  595.     case PHASE_STAT_MSG_IN:
  596.     if (!(interruptReg & IR_DISCNCT)) {
  597.         printf("SCSIC90: Should have seen end of I/O.\n");
  598.         status = FAILURE;
  599.     }
  600.     break;
  601.     case PHASE_RDY_DISCON:
  602.     if (interruptReg & IR_DISCNCT) {
  603.         PUTCIRCBUF(CSTR,"intr: targ ");
  604.         PUTCIRCBUF(CBYTE, (char *)devPtr->targetID);
  605.         PUTCIRCBUF(CSTR," discon.");
  606.         PUTCIRCNULL;
  607.         devPtr->lastPhase = PHASE_BUS_FREE;
  608.         SET_CTRL_FREE(ctrlPtr);
  609.         PerformCmdDone(ctrlPtr,status);
  610.         MASTER_UNLOCK(&(ctrlPtr->mutex));
  611.         return TRUE;
  612.     } else {
  613.         printf("SCSIC90: expecting disconnect signal.\n");
  614.         status = FAILURE;
  615.     }
  616.     break;
  617.     default:
  618.     /* We set this field, so this shouldn't happen. */
  619.     printf("SCSIC90Intr: We came from an unknown phase.\n");
  620.     status = FAILURE;
  621.     break;
  622.     }
  623.  
  624.     if ((status != SUCCESS) || (interruptReg & IR_DISCNCT)) {
  625.         PUTCIRCBUF(CSTR,"intr: exit stat ");
  626.         PUTCIRCBUF(CBYTE,(char *)status);
  627.         PUTCIRCNULL;
  628.     RequestDone(devPtr,
  629.             devPtr->scsiCmdPtr,
  630.             status,
  631.             devPtr->commandStatus,
  632.             devPtr->scsiCmdPtr->bufferLen - devPtr->activeBufLen);
  633.     PerformCmdDone(ctrlPtr,status);
  634.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  635.     return TRUE;
  636.     }
  637.  
  638.     switch (phase) {
  639.  
  640.     case SR_DATA_OUT:
  641.     case SR_DATA_IN:
  642.     devPtr->lastPhase = (phase == SR_DATA_OUT ? PHASE_DATA_OUT :
  643.                  PHASE_DATA_IN);
  644.     /*
  645.      * It should be possible to do multiple blocks of DMA without
  646.      * returning to the higher level, if we set the max transfer size
  647.      * larger, but we don't handle that yet. XXX
  648.      */
  649. #ifdef sun4c
  650.     dmaControllerActive++;    /* Resetting controller not allowed. */
  651. #endif
  652.     PUTCIRCBUF(CSTR,"start dma ptr: ");
  653.     PUTCIRCBUF(CINT,(char *)devPtr->activeBufPtr);
  654.     PUTCIRCBUF(CSTR,"; len: ");
  655.     PUTCIRCBUF(CINT,(char *)devPtr->activeBufLen);
  656.     PUTCIRCNULL;
  657.     DevStartDMA(ctrlPtr);
  658.     break;
  659.     case SR_COMMAND:
  660.     charPtr = devPtr->scsiCmdPtr->commandBlock;
  661.     PUTCIRCBUF(CSTR,"cmd:");
  662.     for (i = 0; i < devPtr->scsiCmdPtr->commandBlockLen; i++) {
  663.         circBuf[circHead] = ' ';
  664.         circHead = (circHead + 1) % CIRCBUFLEN;
  665.         PUTCIRCBUF(CBYTE, (char *)*charPtr);
  666.         regsPtr->scsi_ctrl.write.FIFO = *charPtr;
  667.         charPtr++;
  668.     }
  669.     PUTCIRCNULL;
  670.     devPtr->lastPhase = PHASE_COMMAND;
  671.     regsPtr->scsi_ctrl.write.synchPer = devPtr->synchPeriod;
  672.     regsPtr->scsi_ctrl.write.synchOffset = devPtr->synchOffset;
  673.     regsPtr->scsi_ctrl.write.command = CR_XFER_INFO;
  674.     break;
  675.     case SR_STATUS:
  676.     /*
  677.      * We're in status phase.  If all goes right, the next interrupt
  678.      * will be after we've handled the message phase as well, although
  679.      * the phase will say we're in message phase.
  680.      */
  681.     devPtr->lastPhase = PHASE_STATUS;
  682.     regsPtr->scsi_ctrl.write.command = CR_INIT_COMP;
  683.     break;
  684.     case SR_MSG_OUT:
  685.     i = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  686.     if (i > 0) {
  687.         PUTCIRCBUF(CSTR,"msg-out: fifo: ");
  688.         while (i-- > 0) {
  689.         circBuf[circHead] = ' ';
  690.         circHead = (circHead + 1) % CIRCBUFLEN;
  691.         tempChar = regsPtr->scsi_ctrl.read.FIFO;
  692.         PUTCIRCBUF(CBYTE,(char*)(tempChar));
  693.         }
  694.         PUTCIRCNULL;
  695.     }
  696.     PUTCIRCBUF(CSTR,"msg-out: msg: ");
  697.     for (i=0; i<devPtr->messageBufLen; i++) {
  698.         circBuf[circHead] = ' ';
  699.         circHead = (circHead + 1) % CIRCBUFLEN;
  700.         PUTCIRCBUF(CBYTE, (char *)devPtr->messageBuf[i]);
  701.         regsPtr->scsi_ctrl.write.FIFO = devPtr->messageBuf[i];
  702.         devPtr->messageBuf[i] = '\0';
  703.     }
  704.     PUTCIRCNULL;
  705.     regsPtr->scsi_ctrl.write.command = CR_XFER_INFO;
  706.     devPtr->lastPhase = PHASE_MSG_OUT;
  707.     devPtr->messageBufLen = 0;
  708.     status = regsPtr->scsi_ctrl.read.status;
  709.     if (status & SR_GE) {
  710.         panic("gross error 2");
  711.     }
  712.     break;
  713.     case SR_MSG_IN:
  714.     /* request incoming message xfer */
  715.     regsPtr->scsi_ctrl.write.command = CR_XFER_INFO;
  716.     devPtr->lastPhase = PHASE_MSG_IN;
  717.     break;
  718.     default:
  719.     printf("unknown scsi phase type: 0x%02x\n", (int)phase);
  720.     status = FAILURE;
  721.     break;
  722.     }
  723.  
  724.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  725.     return TRUE;
  726. }
  727.  
  728. /*
  729.  *----------------------------------------------------------------------
  730.  *
  731.  * PerformCmdDone
  732.  *
  733.  *    Do cleanup after final phase of command.
  734.  *
  735.  * Results:
  736.  *    None.
  737.  *
  738.  * Side effects:
  739.  *    Calls RequestDone routine to invoke callback
  740.  *      and then gets next item of queue set.
  741.  *
  742.  *----------------------------------------------------------------------
  743.  */
  744. static void
  745. PerformCmdDone(ctrlPtr,status)
  746. Controller   *ctrlPtr;
  747. ReturnStatus status;
  748. {
  749.     List_Links        *newRequestPtr;
  750.     ClientData        clientData;
  751.  
  752.     ctrlPtr->regsPtr->scsi_ctrl.write.command = CR_EN_SLCT;
  753.     if (IS_CTRL_FREE(ctrlPtr)) {
  754.     if (ctrlPtr->interruptDevPtr == (Device *)NIL) {
  755.         newRequestPtr = Dev_QueueGetNextFromSet(ctrlPtr->devQueues,
  756.                         ctrlPtr->devQueuesMask,
  757.                         &clientData);
  758.         PUTCIRCBUF(CSTR,"cdone: cmd ");
  759.         PUTCIRCBUF(CINT,(char *)newRequestPtr);
  760.         PUTCIRCNULL;
  761.     } else {
  762.         clientData = (ClientData)(ctrlPtr->interruptDevPtr);
  763.         newRequestPtr=(List_Links *)(ctrlPtr->interruptDevPtr->scsiCmdPtr);
  764.         SET_DEV_FREE(ctrlPtr->interruptDevPtr);
  765.         ctrlPtr->interruptDevPtr = (Device *)NIL;
  766.         PUTCIRCBUF(CSTR,"cdone: resend dev ");
  767.         PUTCIRCBUF(CINT, (char *)clientData);
  768.         PUTCIRCBUF(CSTR," cmd ");
  769.         PUTCIRCBUF(CINT,(char *)newRequestPtr);
  770.         PUTCIRCNULL;
  771.     }
  772.     if (newRequestPtr != (List_Links *) NIL) {
  773.         (void) DevEntryAvailProc(clientData, newRequestPtr);
  774.     }
  775.     } else {
  776.     PUTCIRCBUF(CSTR,"cdone: busy ");
  777.     PUTCIRCNULL;
  778.     }
  779.  
  780. }
  781.  
  782. /*
  783.  *----------------------------------------------------------------------
  784.  *
  785.  * PerformSelect
  786.  *
  787.  *    Interpret select phase
  788.  *
  789.  * Results:
  790.  *    None.
  791.  *
  792.  * Side effects:
  793.  *    None.
  794.  *
  795.  *----------------------------------------------------------------------
  796.  */
  797. static ReturnStatus
  798. PerformSelect(ctrlPtr, interruptReg, sequenceReg)
  799. Controller      *ctrlPtr;
  800. unsigned int    interruptReg;
  801. unsigned int    sequenceReg;
  802. {
  803.     Device   *devPtr = ctrlPtr->devPtr;
  804.     static char *errMsg[] = {
  805.     "No error",
  806.     "target timed out",
  807.     "no message-out phase",
  808.     "no command phase",
  809.     "command phase incomplete",
  810.     "unknown sequence error"
  811.     };
  812.     int msgNum;
  813.     ReturnStatus status = SUCCESS;
  814.  
  815.     switch(sequenceReg) {
  816.     case SEQ_COMPLETE:
  817.     msgNum = 0;
  818.     break;
  819.     case SEQ_NO_SEL:
  820.     if (interruptReg & IR_DISCNCT) {
  821.         msgNum = 1;
  822.     } else if (!(devPtr->msgFlag & REQEXTENDEDMSG)) {
  823.         msgNum = 2;
  824.     } else {
  825.         msgNum = 0;
  826.         devPtr->msgFlag &= ~REQEXTENDEDMSG;
  827.         devPtr->messageBuf[0] = SCSI_EXTENDED_MESSAGE;
  828.         devPtr->messageBuf[1] = 3;
  829.         devPtr->messageBuf[2] = SCSI_EXTENDED_MSG_SYNC;
  830.         devPtr->messageBuf[3] = NCR_TO_SCSI(MIN_SYNCH_PERIOD);
  831.         devPtr->messageBuf[4] = MAX_SYNCH_OFFSET;
  832.         devPtr->messageBufLen = 5;
  833.     }
  834.     break;
  835.     case SEQ_NO_CMD:
  836.     msgNum = 3;
  837.     break;
  838.     case SEQ_CMD_INCOMPLETE:
  839.     msgNum = 4;
  840.     break;
  841.     default:
  842.     msgNum = 5;
  843.     break;
  844.     }
  845.     
  846.     if (msgNum) {
  847.     ctrlPtr->regsPtr->scsi_ctrl.write.command = CR_FLSH_FIFO;
  848.     status = FAILURE;
  849.     printf("%s: selection failed: %s\n",
  850.            ctrlPtr->devPtr->handle.locationName,
  851.            errMsg[msgNum]);
  852.     }
  853.     
  854.     return status;
  855.  
  856.  
  857. /*
  858.  *----------------------------------------------------------------------
  859.  *
  860.  * PerformDataXfer
  861.  *
  862.  *    Interpret data-in, data-out condition
  863.  *
  864.  * Results:
  865.  *    None.
  866.  *
  867.  * Side effects:
  868.  *    None.
  869.  *
  870.  *----------------------------------------------------------------------
  871.  */
  872. static ReturnStatus
  873. PerformDataXfer(ctrlPtr, interruptReg, statusReg)
  874. Controller      *ctrlPtr;
  875. unsigned int    interruptReg;
  876. unsigned int    statusReg;
  877. {
  878.     ReturnStatus status = SUCCESS;
  879.     volatile CtrlRegs    *regsPtr = ctrlPtr->regsPtr;
  880.     Device         *devPtr = ctrlPtr->devPtr;
  881.     unsigned char  fifoCnt;
  882.     int            residual;
  883.     int           amountXfered;
  884.  
  885.     if (interruptReg & IR_DISCNCT) {
  886.     printf("%s disconnected or timed out during data xfer.\n",
  887.            devPtr->handle.locationName);
  888.     return DEV_TIMEOUT;
  889.     }
  890.  
  891. #ifdef sun4c
  892.     dmaControllerActive--;
  893.     MACH_DELAY(100);
  894. #endif
  895.     residual = regsPtr->scsi_ctrl.read.xCntLo;
  896. #ifdef sun4c
  897.     MACH_DELAY(100);
  898. #endif
  899.     residual += (regsPtr->scsi_ctrl.read.xCntHi << 8);
  900.     fifoCnt = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  901.     residual += fifoCnt;
  902.     /*
  903.      * If the transfer was the maximum, 64K bytes, a 0 in the counter
  904.      * may mean that nothing was transfered...  What should I do? XXX
  905.      */
  906.  
  907.     PUTCIRCBUF(CSTR,"residual: ");
  908.     PUTCIRCBUF(CINT,(char *)(residual));
  909.     PUTCIRCBUF(CSTR,"; fifoCnt ");
  910.     PUTCIRCBUF(CINT,(char *)(fifoCnt));
  911.     PUTCIRCNULL;
  912.     regsPtr->scsi_ctrl.write.command = CR_FLSH_FIFO;
  913.  
  914.     /*
  915.      * Flush the cache on data in, since the dma put it into memory
  916.      * but didn't go through the cache.  We don't have to worry about this
  917.      * on writes, since the sparcstation has a write-through cache.
  918.      */
  919.     amountXfered = devPtr->activeBufLen - residual;
  920.     if (devPtr->lastPhase == PHASE_DATA_IN) {
  921.     FLUSH_BYTES((char *) ctrlPtr->buffer, devPtr->activeBufPtr, 
  922.             amountXfered);
  923.     }
  924.     devPtr->activeBufPtr += amountXfered;
  925.     devPtr->activeBufLen = residual;
  926.  
  927.     if (! (interruptReg & IR_BUS_SERV)) {
  928.     /* Target didn't request information transfer phase. */
  929.     printf("Didn't receive bus service signal after DMA xfer.\n");
  930.     status = FAILURE;
  931.     }
  932.  
  933.     return status;
  934.  
  935. }
  936.  
  937. /*
  938.  *----------------------------------------------------------------------
  939.  *
  940.  * PerformStatus
  941.  *
  942.  *    Interpret status condition
  943.  *
  944.  * Results:
  945.  *    None.
  946.  *
  947.  * Side effects:
  948.  *    None.
  949.  *
  950.  *----------------------------------------------------------------------
  951.  */
  952. static ReturnStatus
  953. PerformStatus(ctrlPtr, interruptReg)
  954. Controller      *ctrlPtr;
  955. unsigned int    interruptReg;
  956. {
  957.     volatile CtrlRegs    *regsPtr = ctrlPtr->regsPtr;
  958.     Device              *devPtr = ctrlPtr->devPtr;
  959.     int            numBytes;
  960.     unsigned            char message;
  961.  
  962.     devPtr->lastPhase = PHASE_STAT_MSG_IN;
  963.     /* Read bytes from FIFO. */
  964.     numBytes = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  965.     if (numBytes != 2) {
  966.     /* We didn't get both phases. */
  967.     printf("SCSIC90: Missing message byte after status phase byte.\n");
  968.     return(FAILURE);
  969.     }
  970.     devPtr->commandStatus = regsPtr->scsi_ctrl.read.FIFO;
  971.     devPtr->commandStatus &= SCSI_STATUS_MASK;
  972.     message = regsPtr->scsi_ctrl.read.FIFO;
  973.     if (! (interruptReg & IR_FUNC_COMP)) {
  974.     printf("SCSIC90: Command didn't complete.\n");
  975.     return(FAILURE);
  976.     }
  977.  
  978.     if (message != SCSI_COMMAND_COMPLETE) {
  979.     printf("SCSIC90: Expecting cmd_complete msg from %s, got ",
  980.            ctrlPtr->devPtr->handle.locationName);
  981.     PrintMsg((unsigned int) message);
  982.     return(FAILURE);
  983.     }
  984.     regsPtr->scsi_ctrl.write.command = CR_MSG_ACCPT;
  985.     
  986.     return SUCCESS;
  987. }
  988.  
  989. /*
  990.  *----------------------------------------------------------------------
  991.  *
  992.  * PerformMsgIn
  993.  *
  994.  *    Interpret msg_in condition
  995.  *
  996.  * Results:
  997.  *    None.
  998.  *
  999.  * Side effects:
  1000.  *    None.
  1001.  *
  1002.  *----------------------------------------------------------------------
  1003.  */
  1004. static ReturnStatus
  1005. PerformMsgIn(ctrlPtr)
  1006. Controller *ctrlPtr;
  1007. {
  1008.     ReturnStatus status = SUCCESS;
  1009.     Device *devPtr = ctrlPtr->devPtr;
  1010.     volatile CtrlRegs *regsPtr = ctrlPtr->regsPtr;
  1011.     unsigned char message;
  1012.  
  1013.     message = regsPtr->scsi_ctrl.read.FIFO;
  1014.  
  1015.     PUTCIRCBUF(CSTR,"msg in: ");
  1016.     PUTCIRCBUF(CBYTE, (char *)message);
  1017.     PUTCIRCNULL;
  1018.  
  1019.     if (devPtr->msgFlag & STARTEXTENDEDMSG) { 
  1020.     status = PerformExtendedMsgIn(ctrlPtr,(unsigned int)message);
  1021.     return status;
  1022.     }
  1023.  
  1024.     switch(message) {
  1025.     case SCSI_COMMAND_COMPLETE:
  1026.     /* this is handled in that stat_msg_in phase */
  1027.     printf("not expecting command_complete msg.\n");
  1028.     status = FAILURE;
  1029.     break;
  1030.     case SCSI_DISCONNECT:
  1031.     devPtr->lastPhase = PHASE_RDY_DISCON;
  1032.     break;
  1033.     case SCSI_SAVE_DATA_POINTER:
  1034.     /* No need to save anything since we keep the current
  1035.      * data ptr in activeBufPtr anyway. */
  1036.     devPtr->lastPhase = PHASE_BUS_FREE;
  1037.     PUTCIRCBUF(CSTR,"save: ptr ");
  1038.     PUTCIRCBUF(CINT, (char *)devPtr->activeBufPtr);
  1039.     PUTCIRCBUF(CSTR,"; len ");
  1040.     PUTCIRCBUF(CINT, (char *)devPtr->activeBufLen);
  1041.     PUTCIRCNULL;
  1042.     break;
  1043.     case SCSI_RESTORE_POINTERS:
  1044.     /* No need to restore anything, since we keep the
  1045.      * current data ptr in activeBufPtr anyway. */
  1046.     devPtr->lastPhase = PHASE_BUS_FREE;
  1047.     PUTCIRCBUF(CSTR,"restore: ptr ");
  1048.     PUTCIRCBUF(CINT, (char *)devPtr->activeBufPtr);
  1049.     PUTCIRCBUF(CSTR,"; len ");
  1050.     PUTCIRCBUF(CINT, (char *)devPtr->activeBufLen);
  1051.     PUTCIRCNULL;
  1052.     break;
  1053.     case SCSI_IDENTIFY:
  1054.     devPtr->lastPhase = PHASE_BUS_FREE;
  1055.     break;
  1056.     case SCSI_EXTENDED_MESSAGE:
  1057.     devPtr->msgFlag |= STARTEXTENDEDMSG;
  1058.     status = PerformExtendedMsgIn(ctrlPtr,(unsigned int)message);
  1059.     return status;
  1060.     break;
  1061.     case SCSI_MESSAGE_REJECT:
  1062.     /* kill any synchronous agreement in effect */
  1063.     devPtr->synchPeriod = MIN_SYNCH_PERIOD;
  1064.     devPtr->synchOffset = 0;
  1065.     devPtr->lastPhase = PHASE_BUS_FREE;
  1066.     devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1067.     break;
  1068.     default:
  1069.     PUTCIRCBUF(CSTR,"Msg-in: unknown msg");
  1070.     PUTCIRCNULL;
  1071.     printf("SCSIC90: Couldn't handle msg type: 0x%02x\n",message);
  1072.     regsPtr->scsi_ctrl.write.command = CR_SET_ATN;
  1073.     devPtr->lastPhase = PHASE_BUS_FREE;
  1074.     break;
  1075.     }
  1076.  
  1077.     regsPtr->scsi_ctrl.write.command = CR_MSG_ACCPT;
  1078.  
  1079.     return status;
  1080.  
  1081. } /* PerformMsgIn */
  1082.  
  1083. /*
  1084.  *----------------------------------------------------------------------
  1085.  *
  1086.  * PerformExtendedMsgIn
  1087.  *
  1088.  *    Interpret extended msg_in condition
  1089.  *
  1090.  * Results:
  1091.  *    status.
  1092.  *
  1093.  * Side effects:
  1094.  *      Sets the values for synchronous xfer in the device structure.
  1095.  *
  1096.  *    We get the bytes of the extended msg 1 at a time.
  1097.  *      Format: extended msg indicator : 0x01 
  1098.  *                       msg length    : 0x?? 
  1099.  *                       msg code      : 0x03 (we only do 1 type) 
  1100.  *                       msg param1    : 0x?? (should be synch_period)
  1101.  *                       msg param2    : 0x?? (should be synch_offset)
  1102.  *
  1103.  *----------------------------------------------------------------------
  1104.  */
  1105. static ReturnStatus
  1106. PerformExtendedMsgIn(ctrlPtr, message)
  1107. Controller *ctrlPtr;
  1108. unsigned int message;
  1109. {
  1110.     ReturnStatus status = SUCCESS;
  1111.     Device *devPtr      = ctrlPtr->devPtr;
  1112.     volatile CtrlRegs *regsPtr = ctrlPtr->regsPtr;
  1113.     int len             = devPtr->messageBufLen;
  1114.     unsigned char periodInClks;
  1115.     unsigned char period;
  1116.     unsigned char offset;
  1117.     int i;
  1118.  
  1119.     devPtr->messageBuf[len] = message;
  1120.     devPtr->messageBufLen++;
  1121.  
  1122.     switch(len) {
  1123.     case 0: /* extended msg code 0x01 */
  1124.     devPtr->lastPhase = PHASE_BUS_FREE;
  1125.     break;
  1126.     case 1: /* msg length. i.e. # bytes to follow this one */
  1127.     devPtr->lastPhase = PHASE_BUS_FREE;
  1128.     break;
  1129.     case 2: /* extended msg code */
  1130.     if ((message != SCSI_EXTENDED_MSG_SYNC) ||
  1131.         (devPtr->messageBuf[1] != 3)) {
  1132.         PUTCIRCBUF(CSTR,"Msg-in: bad xtend msg: ");
  1133.         PUTCIRCBUF(CBYTE,(char *)(message));
  1134.         PUTCIRCBUF(CSTR,"; len ");
  1135.         PUTCIRCBUF(CBYTE,(char *)(devPtr->messageBuf[1]));
  1136.         PUTCIRCNULL;
  1137.         panic("bad xtend msg");
  1138.         devPtr->messageBuf[0] = SCSI_MESSAGE_REJECT;
  1139.         devPtr->messageBufLen = 1;
  1140.         regsPtr->scsi_ctrl.write.command = CR_SET_ATN;
  1141.         devPtr->lastPhase = PHASE_MSG_OUT;
  1142.         devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1143.     } else {
  1144.         devPtr->lastPhase = PHASE_BUS_FREE;
  1145.     }
  1146.     break;
  1147.     case 3: /* synch_period */
  1148.     devPtr->lastPhase = PHASE_BUS_FREE;
  1149.     break;
  1150.     case 4: /* synch_offset */
  1151.     /* 
  1152.      * Now we have both the period and the offset.
  1153.      */
  1154.     period = devPtr->messageBuf[3];
  1155.     offset = devPtr->messageBuf[4];
  1156.     periodInClks = SCSI_TO_NCR(period);
  1157.     /* if values are acceptable, install them else negotiate */
  1158.     if ((periodInClks >= MIN_SYNCH_PERIOD) &&
  1159.         (offset <= MAX_SYNCH_OFFSET)) {
  1160.         PUTCIRCBUF(CSTR,"accept per: ");
  1161.         PUTCIRCBUF(CBYTE,(char *)period);
  1162.         PUTCIRCBUF(CSTR,"; per clk ");
  1163.         PUTCIRCBUF(CBYTE,(char *)periodInClks);
  1164.         PUTCIRCBUF(CSTR,"; off ");
  1165.         PUTCIRCBUF(CBYTE,(char *)offset);
  1166.         PUTCIRCNULL;
  1167.         devPtr->synchPeriod = periodInClks; 
  1168.         devPtr->synchOffset = offset;
  1169.         devPtr->lastPhase = PHASE_BUS_FREE;
  1170.         devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1171.     } else {
  1172.         if (periodInClks < devPtr->synchPeriod) {
  1173.         devPtr->messageBuf[3] = NCR_TO_SCSI(MIN_SYNCH_PERIOD);
  1174.         }
  1175.         if (offset > devPtr->synchOffset) {
  1176.         devPtr->messageBuf[4] = MAX_SYNCH_OFFSET;
  1177.         }
  1178.         PUTCIRCBUF(CSTR,"negotiate per: ");
  1179.         PUTCIRCBUF(CBYTE,(char *)(devPtr->messageBuf[3]));
  1180.         PUTCIRCBUF(CSTR,"; off ");
  1181.         PUTCIRCBUF(CBYTE,(char *)(devPtr->messageBuf[4]));
  1182.         PUTCIRCNULL;
  1183.         regsPtr->scsi_ctrl.write.command = CR_SET_ATN;
  1184.         devPtr->lastPhase = PHASE_MSG_OUT;
  1185.         devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1186.     }
  1187.     break;
  1188.     default:
  1189.     printf("SCSIC90: xmsg case error\n");
  1190.     devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1191.     status = FALSE;
  1192.     break;
  1193.     }
  1194.     PUTCIRCBUF(CSTR,"Xmsg-in: accept msg");
  1195.     len = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  1196.     PUTCIRCBUF(CSTR,"; FIFO:");
  1197.     for(i=0;i<len;i++) {
  1198.     circBuf[circHead] = ' ';
  1199.     circHead = (circHead + 1) % CIRCBUFLEN;
  1200.     offset = regsPtr->scsi_ctrl.read.FIFO;
  1201.     PUTCIRCBUF(CBYTE, (char *)offset);
  1202.     }
  1203.     PUTCIRCBUF(CSTR,"; mbuf:");
  1204.     for(i=0;i<devPtr->messageBufLen;i++) {
  1205.     circBuf[circHead] = ' ';
  1206.     circHead = (circHead + 1) % CIRCBUFLEN;
  1207.     PUTCIRCBUF(CBYTE, (char *)(devPtr->messageBuf[i]));
  1208.     }
  1209.     PUTCIRCNULL;
  1210.     regsPtr->scsi_ctrl.write.command = CR_MSG_ACCPT;
  1211.     return status;
  1212.  
  1213. /*
  1214.  *----------------------------------------------------------------------
  1215.  *
  1216.  * PerformReselect
  1217.  *
  1218.  *    Reconnect a logical unit
  1219.  *
  1220.  * Results:
  1221.  *    None.
  1222.  *
  1223.  * Side effects:
  1224.  *    None.
  1225.  *
  1226.  *----------------------------------------------------------------------
  1227.  */
  1228. static ReturnStatus
  1229. PerformReselect(ctrlPtr, interruptReg)
  1230. Controller      *ctrlPtr;
  1231. unsigned int    interruptReg;
  1232. {
  1233.     volatile CtrlRegs *regsPtr = ctrlPtr->regsPtr;
  1234.     Device            *devPtr;
  1235.     unsigned char     target;
  1236.     unsigned char     ourID;
  1237.     unsigned char     message;
  1238.     int               fifoCnt,i;
  1239.  
  1240.     /* The ID of the target which is requesting reselection comes over 
  1241.      * the bus encoded, not 0-7.  The encoding is the logical OR of 
  1242.      * two bytes: one with the i'th bit set (for target #i) and
  1243.      * one with the host's bit set (usually #7). Unfortunately,
  1244.      * the host's ID is kindly provided to us in binary so we perform
  1245.      * a little transformation...
  1246.      */
  1247.     target = regsPtr->scsi_ctrl.read.FIFO;
  1248.     ourID = regsPtr->scsi_ctrl.read.config1 & C1_BUS_ID;
  1249.     ourID = ~(1 << ourID);
  1250.  
  1251.     switch(target & ourID) {
  1252.     case 0x01:
  1253.     target = 0;
  1254.     break;
  1255.     case 0x02:
  1256.     target = 1;
  1257.     break;
  1258.     case 0x04:
  1259.     target = 2;
  1260.     break;
  1261.     case 0x08:
  1262.     target = 3;
  1263.     break;
  1264.     case 0x10:
  1265.     target = 4;
  1266.     break;
  1267.     case 0x20:
  1268.     target = 5;
  1269.     break;
  1270.     case 0x40:
  1271.     target = 6;
  1272.     break;
  1273.     case 0x80:
  1274.     target = 7;
  1275.     break;
  1276.     default:
  1277.     printf("SCSIC90: couldn't decode target ID 0x%02x\n", target);
  1278.     return FAILURE;
  1279.     }
  1280.  
  1281.     message = regsPtr->scsi_ctrl.read.FIFO;    
  1282.  
  1283.     if (!(message & SCSI_IDENTIFY)) {
  1284.     printf("SCSIC90: Expected Identify msg after reselect, got 0x%02x.\n",
  1285.            message);
  1286.     return FAILURE;
  1287.     }
  1288.     message &= SCSI_IDENT_LUN_MASK;
  1289.  
  1290.     devPtr = ctrlPtr->devicePtr[target][message];
  1291.  
  1292.     fifoCnt = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  1293.     PUTCIRCBUF(CSTR,"resel: targ ");
  1294.     PUTCIRCBUF(CBYTE, (char *)target);
  1295.     PUTCIRCBUF(CSTR,"; lun ");
  1296.     PUTCIRCBUF(CBYTE, (char *)message);
  1297.     ourID = regsPtr->scsi_ctrl.read.command;
  1298.     PUTCIRCBUF(CSTR,"; cmdreg:");
  1299.     PUTCIRCBUF(CBYTE,(char *)ourID);
  1300.     PUTCIRCBUF(CSTR,"; FIFO:");
  1301.     for(i=0;i<fifoCnt;i++) {
  1302.     circBuf[circHead] = ' ';
  1303.     circHead = (circHead + 1) % CIRCBUFLEN;
  1304.     ourID = regsPtr->scsi_ctrl.read.FIFO;
  1305.     PUTCIRCBUF(CBYTE, (char *)ourID);
  1306.     }
  1307.     PUTCIRCNULL;
  1308.  
  1309.     if (IS_DEV_FREE(devPtr)) {
  1310.     panic("resel: device is free.\n");
  1311.     }
  1312.  
  1313.     /*
  1314.      * It's possible for the reselection interrupt to occur just
  1315.      * when we were sending a new command.  Three cases:
  1316.      *  1) Interrupt happened before loading any cmd bytes.
  1317.      *     Only indication is that controller is busy.
  1318.      *  2) Interrupt happened before the send; part of the
  1319.      *     cmd in the fifo.
  1320.      *  3) Interrupt happened during the arbitration/selection
  1321.      *     phases of the send; the bus_serv bit will be set.
  1322.      * Note that the 53C90 doesn't handle this situation quite
  1323.      * the same as the later 53C94, 53C95 chips. The older chip
  1324.      * accepts cmd bytes after it shouldn't so there may be bytes
  1325.      * in the FIFO now that should be here. See the manual.
  1326.      */
  1327.  
  1328.  
  1329.     /* An restore_data_ pointer cmd is implied by a reselect
  1330.      * but we don't need to do anything */
  1331.     regsPtr->scsi_ctrl.write.command = CR_MSG_ACCPT;
  1332.  
  1333.     if (!(IS_CTRL_FREE(ctrlPtr)) ||
  1334.     (interruptReg & IR_BUS_SERV) ||
  1335.     (fifoCnt > 0)) {
  1336.     PUTCIRCBUF(CSTR,"resel: save dev ");
  1337.     PUTCIRCBUF(CINT, (char *)ctrlPtr->devPtr);
  1338.     PUTCIRCBUF(CSTR," cmd ");
  1339.     PUTCIRCBUF(CINT, (char *)ctrlPtr->devPtr->scsiCmdPtr);
  1340.     PUTCIRCNULL;
  1341.     ctrlPtr->interruptDevPtr = ctrlPtr->devPtr;
  1342.     regsPtr->scsi_ctrl.write.command = CR_FLSH_FIFO;
  1343.     }
  1344.  
  1345.     SET_CTRL_BUSY(ctrlPtr,devPtr);
  1346.  
  1347.     return SUCCESS;
  1348. }
  1349.  
  1350. /*
  1351.  *----------------------------------------------------------------------
  1352.  *
  1353.  * ReleaseProc --
  1354.  *
  1355.  *    Device release proc for controller.
  1356.  *
  1357.  * Results:
  1358.  *    None.
  1359.  *
  1360.  * Side effects:
  1361.  *    None.
  1362.  *
  1363.  *----------------------------------------------------------------------
  1364.  */
  1365. /*ARGSUSED*/
  1366. static ReturnStatus
  1367. ReleaseProc(scsiDevicePtr)
  1368.     ScsiDevice    *scsiDevicePtr;
  1369. {
  1370.     return SUCCESS;
  1371. }
  1372.  
  1373.  
  1374. /*
  1375.  *----------------------------------------------------------------------
  1376.  *
  1377.  * DevSCSIC90AttachDevice --
  1378.  *
  1379.  *    Attach a SCSI device using the Sun SCSIC90 HBA. 
  1380.  *
  1381.  * Results:
  1382.  *    None.
  1383.  *
  1384.  * Side effects:
  1385.  *    None.
  1386.  *
  1387.  *----------------------------------------------------------------------
  1388.  */
  1389.  
  1390. ScsiDevice   *
  1391. DevSCSIC90AttachDevice(devicePtr, insertProc)
  1392.     Fs_Device    *devicePtr;     /* Device to attach. */
  1393.     void    (*insertProc)(); /* Queue insert procedure. */
  1394. {
  1395.     Device *devPtr;
  1396.     Controller    *ctrlPtr;
  1397.     char   tmpBuffer[512];
  1398.     int       length;
  1399.     int       ctrlNum;
  1400.     int       targetID, lun;
  1401.  
  1402.     /*
  1403.      * First find the SCSIC90 controller this device is on.
  1404.      */
  1405.     ctrlNum = SCSI_HBA_NUMBER(devicePtr);
  1406.     if ((ctrlNum > MAX_SCSIC90_CTRLS) ||
  1407.     (Controllers[ctrlNum] == (Controller *) 0)) { 
  1408.     return (ScsiDevice  *) NIL;
  1409.     } 
  1410.     ctrlPtr = Controllers[ctrlNum];
  1411.     targetID = SCSI_TARGET_ID(devicePtr);
  1412.     lun = SCSI_LUN(devicePtr);
  1413.     /*
  1414.      * Allocate a device structure for the device and fill in the
  1415.      * handle part. This must be created before we grap the MASTER_LOCK.
  1416.      */
  1417.     devPtr = (Device *) malloc(sizeof(Device)); 
  1418.     bzero((char *) devPtr, sizeof(Device));
  1419.     devPtr->handle.devQueue = Dev_QueueCreate(ctrlPtr->devQueues,
  1420.                           (1<<targetID),
  1421.                           insertProc,
  1422.                           (ClientData) devPtr);
  1423.     devPtr->handle.locationName = "Unknown";
  1424.     devPtr->handle.LUN = lun;
  1425.     devPtr->handle.releaseProc = ReleaseProc;
  1426.     devPtr->handle.maxTransferSize = MAX_TRANSFER_SIZE;
  1427.     devPtr->targetID = targetID;
  1428.     devPtr->ctrlPtr = ctrlPtr;
  1429.     devPtr->synchPeriod = 0;
  1430.     devPtr->synchOffset = 0;
  1431.     devPtr->msgFlag = 0;
  1432.     MASTER_LOCK(&(ctrlPtr->mutex));
  1433.     /*
  1434.      * A device pointer of zero means that targetID/LUN 
  1435.      * conflicts with that of the HBA. A NIL means the
  1436.      * device hasn't been attached yet.
  1437.      */
  1438.     if (ctrlPtr->devicePtr[targetID][lun] == (Device *) 0) {
  1439.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1440.     (void) Dev_QueueDestroy(devPtr->handle.devQueue);
  1441.     free((char *) devPtr);
  1442.     return (ScsiDevice *) NIL;
  1443.     }
  1444.     if (ctrlPtr->devicePtr[targetID][lun] != (Device *) NIL) {
  1445.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1446.     (void) Dev_QueueDestroy(devPtr->handle.devQueue);
  1447.     free((char *) devPtr);
  1448.     return (ScsiDevice *) (ctrlPtr->devicePtr[targetID][lun]);
  1449.     }
  1450.     SET_DEV_FREE(devPtr);
  1451.     ctrlPtr->devicePtr[targetID][lun] = devPtr;
  1452.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1453.     (void) sprintf(tmpBuffer, "%s Target %d LUN %d", ctrlPtr->name, 
  1454.             devPtr->targetID, devPtr->handle.LUN);
  1455.     length = strlen(tmpBuffer);
  1456.     devPtr->handle.locationName = (char *) strcpy(malloc(length+1),tmpBuffer);
  1457.  
  1458.     if (devSCSIC90Debug > 3) {
  1459.     printf("devSCSIC90Attach: attached device %s.\n", tmpBuffer);
  1460.     }
  1461.  
  1462.     return (ScsiDevice *) devPtr;
  1463. }
  1464.  
  1465.  
  1466. /*
  1467.  *----------------------------------------------------------------------
  1468.  *
  1469.  * PrintMsg --
  1470.  *
  1471.  *    Print out the asci string for a scsi msg.
  1472.  *
  1473.  * Results:
  1474.  *    None.
  1475.  *
  1476.  * Side effects:
  1477.  *    None.
  1478.  *
  1479.  *----------------------------------------------------------------------
  1480.  */
  1481. static void
  1482. PrintMsg(msg)
  1483.     unsigned int msg;
  1484. {
  1485.  
  1486.     if (msg & SCSI_IDENTIFY) {
  1487.     if (msg & SCSI_DIS_REC_IDENTIFY) {
  1488.         printf("dis_rec_identify (LUN 0x%02x) msg.\n",
  1489.            (int)(msg & SCSI_IDENT_LUN_MASK));
  1490.     } else {
  1491.         printf("identify (LUN 0x%02x) msg.\n",
  1492.            (int)(msg & SCSI_IDENT_LUN_MASK));
  1493.     }
  1494.     return;
  1495.     } 
  1496.  
  1497.     switch (msg) {
  1498.     case SCSI_COMMAND_COMPLETE:
  1499.     printf("command_complete msg.\n");
  1500.     break;
  1501.     case SCSI_SAVE_DATA_POINTER:
  1502.     printf("save_data_ptr msg.\n");
  1503.     break;
  1504.     case SCSI_RESTORE_POINTERS:
  1505.     printf("restore_ptrs msg.\n");
  1506.     break;
  1507.     case SCSI_DISCONNECT:
  1508.     printf("disconnect msg.\n");
  1509.     break;
  1510.     case SCSI_ABORT:
  1511.     printf("abort msg.\n");
  1512.     break;
  1513.     case SCSI_MESSAGE_REJECT:
  1514.     printf("msg_reject msg.\n");
  1515.     break;
  1516.     case SCSI_NO_OP:
  1517.     printf("no_op msg.\n");
  1518.     break;
  1519.     case SCSI_MESSAGE_PARITY_ERROR:
  1520.     printf("msg_parity msg.\n");
  1521.     break;
  1522.     case SCSI_BUS_RESET:
  1523.     printf("bus_reset msg.\n");
  1524.     break;
  1525.     default:
  1526.     printf("unknown msg %d.\n", msg);
  1527.     break;
  1528.     }
  1529.  
  1530.     return;
  1531. }
  1532.  
  1533.  
  1534. /*
  1535.  *----------------------------------------------------------------------
  1536.  *
  1537.  * PrintPhase --
  1538.  *
  1539.  *    Print out the asci string for a scsi phase.
  1540.  *
  1541.  * Results:
  1542.  *    None.
  1543.  *
  1544.  * Side effects:
  1545.  *    None.
  1546.  *
  1547.  *----------------------------------------------------------------------
  1548.  */
  1549. static void
  1550. PrintPhase(phase)
  1551.     unsigned int    phase;
  1552. {
  1553.     
  1554.     switch (phase) {
  1555.     case SR_DATA_OUT:
  1556.     printf("data out phase.\n");
  1557.     break;
  1558.     case SR_DATA_IN:
  1559.     printf("data in phase.\n");
  1560.     break;
  1561.     case SR_COMMAND:
  1562.     printf("command phase.\n");
  1563.     break;
  1564.     case SR_STATUS:
  1565.     printf("status phase.\n");
  1566.     break;
  1567.     case SR_MSG_OUT:
  1568.     printf("msg out phase.\n");
  1569.     break;
  1570.     case SR_MSG_IN:
  1571.     printf("msg in phase.\n");
  1572.     break;
  1573.     default:
  1574.     printf("unknown phase %d.\n", phase);
  1575.     break;
  1576.     }
  1577.  
  1578.     return;
  1579. }
  1580.  
  1581. /*
  1582.  *----------------------------------------------------------------------
  1583.  *
  1584.  * PrintLastPhase --
  1585.  *
  1586.  *    Print out the asci string for the last scsi phase we were in.
  1587.  *
  1588.  * Results:
  1589.  *    None.
  1590.  *
  1591.  * Side effects:
  1592.  *    None.
  1593.  *
  1594.  *----------------------------------------------------------------------
  1595.  */
  1596. static void
  1597. PrintLastPhase(phase)
  1598.     unsigned int    phase;
  1599. {
  1600.     switch (phase) {
  1601.     case PHASE_BUS_FREE:
  1602.     printf("bus free phase.\n");
  1603.     break;
  1604.     case PHASE_SELECTION:
  1605.     printf("selection phase.\n");
  1606.     break;
  1607.     case PHASE_DATA_OUT:
  1608.     printf("data out phase.\n");
  1609.     break;
  1610.     case PHASE_DATA_IN:
  1611.     printf("data in phase.\n");
  1612.     break;
  1613.     case PHASE_STATUS:
  1614.     printf("status phase.\n");
  1615.     break;
  1616.     case PHASE_MSG_IN:
  1617.     printf("msg in phase.\n");
  1618.     break;
  1619.     case PHASE_STAT_MSG_IN:
  1620.     printf("stat_msg in phase.\n");
  1621.     break;
  1622.     case PHASE_RDY_DISCON:
  1623.     printf("rdy_discon phase.\n");
  1624.     break;
  1625.     default:
  1626.     printf("unknown phase %d.\n", phase);
  1627.     break;
  1628.     }
  1629.  
  1630.     return;
  1631. }
  1632.  
  1633.  
  1634. /*
  1635.  *----------------------------------------------------------------------
  1636.  *
  1637.  * PrintRegs --
  1638.  *
  1639.  *    Print out the interesting registers.  This could be a macro but
  1640.  *    then it couldn't be called from kdbx.  This routine is necessary
  1641.  *    because kdbx doesn't print all the character values properly.
  1642.  *
  1643.  * Results:
  1644.  *    None.
  1645.  *
  1646.  * Side effects:
  1647.  *    Data is displayed on the console or to the debugger.
  1648.  *
  1649.  *----------------------------------------------------------------------
  1650.  */
  1651. static void
  1652. PrintRegs(regsPtr)
  1653.     register volatile CtrlRegs *regsPtr;
  1654. {
  1655.  
  1656.     printf("Won't print interrupt register since that would clear it.\n");
  1657.     printf("xCntLow: 0x%x, xCntHi: 0x%x, FIFO: 0x%x, command: 0x%x,\n",
  1658.         regsPtr->scsi_ctrl.read.xCntLo,
  1659.         regsPtr->scsi_ctrl.read.xCntHi,
  1660.         regsPtr->scsi_ctrl.read.FIFO,
  1661.         regsPtr->scsi_ctrl.read.command);
  1662.     printf("status: 0x%x, sequence: 0x%x, FIFOFlags: 0x%x, config1: 0x%x,\n",
  1663.         regsPtr->scsi_ctrl.read.status,
  1664.         regsPtr->scsi_ctrl.read.sequence,
  1665.         regsPtr->scsi_ctrl.read.FIFOFlags,
  1666.         regsPtr->scsi_ctrl.read.config1);
  1667.     printf("config2: 0x%x, config3: 0x%x\n",
  1668.         regsPtr->scsi_ctrl.read.config2,
  1669.         regsPtr->scsi_ctrl.read.config3);
  1670.  
  1671.     return;
  1672. }
  1673.  
  1674.  
  1675. /*
  1676.  *----------------------------------------------------------------------
  1677.  *
  1678.  *  SpecialSenseProc --
  1679.  *
  1680.  *    Special function used for HBA generated REQUEST SENSE. A SCSI
  1681.  *    command request with this function as a call back proc will
  1682.  *    be processed by routine RequestDone as a result of a 
  1683.  *    REQUEST SENSE. This routine is never called.
  1684.  *
  1685.  * Results:
  1686.  *    None.
  1687.  *
  1688.  * Side effects:
  1689.  *    None.
  1690.  *
  1691.  *----------------------------------------------------------------------
  1692.  */
  1693.  
  1694. static int
  1695. SpecialSenseProc()
  1696. {
  1697.     return 0;
  1698. }
  1699.  
  1700.  
  1701. /*
  1702.  *----------------------------------------------------------------------
  1703.  *
  1704.  * Dev_ChangeScsiDebugLevel --
  1705.  *
  1706.  *    Change the level of debugging info for this scsi driver.
  1707.  *
  1708.  * Results:
  1709.  *    None.
  1710.  *
  1711.  * Side effects:
  1712.  *    A larger or lesser number of messages will be printed out.
  1713.  *
  1714.  *----------------------------------------------------------------------
  1715.  */
  1716. void
  1717. Dev_ChangeScsiDebugLevel(level)
  1718.     int    level;
  1719. {
  1720.     
  1721.     printf("Changing scsi debug level: was %d, ", devSCSIC90Debug);
  1722.     devSCSIC90Debug = level;
  1723.     printf("and is now %d.\n", devSCSIC90Debug);
  1724.  
  1725.     return;
  1726. }
  1727.  
  1728.  
  1729. /*
  1730.  *----------------------------------------------------------------------
  1731.  *
  1732.  * PutCircBuf
  1733.  *
  1734.  *    Stuff data into the circular log buffer
  1735.  *
  1736.  * Results:
  1737.  *    None.
  1738.  *
  1739.  * Side effects:
  1740.  *      None.
  1741.  *
  1742.  *----------------------------------------------------------------------
  1743.  */
  1744. static void
  1745. PutCircBuf(type, object)
  1746. int type;
  1747. char *object;
  1748. {
  1749.     int num = (int)object;
  1750.  
  1751.     switch(type) {
  1752.     case CSTR:
  1753.     while(*object) {
  1754.         circBuf[circHead] = *object++;
  1755.         circHead = (circHead + 1) % CIRCBUFLEN;
  1756.     }
  1757.     break;
  1758.     case CBYTE:
  1759.     circBuf[circHead] = CVTHEX(num,4);
  1760.     circHead = (circHead + 1) % CIRCBUFLEN;
  1761.     circBuf[circHead] = CVTHEX(num,0);
  1762.     circHead = (circHead + 1) % CIRCBUFLEN;
  1763.     break;
  1764.     case CINT:
  1765.     circBuf[circHead] = CVTHEX(num,28); 
  1766.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1767.     circBuf[circHead] = CVTHEX(num,24); 
  1768.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1769.     circBuf[circHead] = CVTHEX(num,20); 
  1770.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1771.     circBuf[circHead] = CVTHEX(num,16); 
  1772.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1773.     circBuf[circHead] = CVTHEX(num,12); 
  1774.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1775.     circBuf[circHead] = CVTHEX(num,8); 
  1776.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1777.     circBuf[circHead] = CVTHEX(num,4); 
  1778.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1779.     circBuf[circHead] = CVTHEX(num,0); 
  1780.     circHead = (circHead + 1) % CIRCBUFLEN;
  1781.     break;
  1782.     default:
  1783.     panic("PutCircBuf: unknown type\n");
  1784.     break;
  1785.     }
  1786. }
  1787.  
  1788.